Podrobný průvodce JavaScript Temporal API, moderním řešením pro efektivní zpracování data a času v různých mezinárodních kontextech.
JavaScript Temporal API: Moderní zpracování data a času pro globální publikum
Objekt `Date` v JavaScriptu je již dlouho zdrojem frustrace pro vývojáře. Jeho měnitelnost, nekonzistentní API a špatná podpora časových pásem vedly ke vzniku mnoha knihoven, jako jsou Moment.js a date-fns, které tyto mezery vyplňovaly. Nyní s příchodem Temporal API nabízí JavaScript moderní, vestavěné řešení pro práci s daty a časy s vylepšenou přehledností a přesností. Tento článek poskytuje komplexní přehled Temporal API se zaměřením na jeho funkce, výhody a použití v různých mezinárodních kontextech.
Co je Temporal API?
Temporal API je nový, globální objekt v JavaScriptu navržený tak, aby řešil nedostatky objektu `Date`. Poskytuje čisté, neměnné (immutable) API pro práci s daty, časy, časovými pásmy a kalendářními systémy. Klíčové je, že se snaží reprezentovat koncepty data a času způsobem, který více odpovídá reálnému použití a očekáváním, což výrazně zjednodušuje internacionalizaci.
Klíčové vlastnosti:
- Neměnnost (Immutability): Objekty Temporal jsou neměnné, což znamená, že operace jako přidání dnů nebo měsíců vracejí nové objekty namísto úpravy původního. Tím se eliminuje běžný zdroj chyb a kód je snáze srozumitelný.
- Přehledné API: Temporal poskytuje konzistentní a intuitivní API pro běžné operace s datem a časem.
- Podpora časových pásem: Temporal zahrnuje robustní podporu pro časová pásma, což umožňuje pracovat s daty a časy v různých lokalitách bez složitostí starého objektu `Date`. Využívá databázi časových pásem IANA, což zaručuje přesné a aktuální informace.
- Kalendářní systémy: Kromě gregoriánského kalendáře podporuje Temporal i alternativní kalendářní systémy, čímž vychází vstříc potřebám různých kultur a regionů.
- Vylepšená přesnost: Temporal nabízí přesnost na nanosekundy, čímž řeší omezení objektu `Date`, který pracuje s milisekundami.
Základní objekty Temporal
Temporal API představuje několik nových typů objektů. Zde jsou některé z těch hlavních:
- `Temporal.PlainDate`: Reprezentuje datum (rok, měsíc, den) bez časového pásma.
- `Temporal.PlainTime`: Reprezentuje čas (hodina, minuta, sekunda, milisekunda, mikrosekunda, nanosekunda) bez data nebo časového pásma.
- `Temporal.PlainDateTime`: Reprezentuje datum a čas bez časového pásma.
- `Temporal.ZonedDateTime`: Reprezentuje datum a čas s konkrétním časovým pásmem.
- `Temporal.Instant`: Reprezentuje konkrétní okamžik v čase, měřený v nanosekundách od epochy Unixu (1. ledna 1970 UTC).
- `Temporal.TimeZone`: Reprezentuje časové pásmo.
- `Temporal.Duration`: Reprezentuje časový úsek (např. 2 hodiny, 30 minut).
- `Temporal.YearMonth`: Reprezentuje rok a měsíc.
- `Temporal.MonthDay`: Reprezentuje měsíc a den.
Práce s daty
Vytvoření `Temporal.PlainDate`
Pro vytvoření `Temporal.PlainDate` můžete použít konstruktor:
const plainDate = new Temporal.PlainDate(2024, 10, 27); // Rok, Měsíc (1-12), Den
console.log(plainDate.toString()); // Výstup: 2024-10-27
Můžete také použít metodu `from`, která přijímá řetězec ve formátu ISO 8601:
const plainDateFromString = Temporal.PlainDate.from('2024-10-27');
console.log(plainDateFromString.toString()); // Výstup: 2024-10-27
Získání složek data
K jednotlivým složkám data můžete přistupovat pomocí vlastností jako `year`, `month` a `day`:
console.log(plainDate.year); // Výstup: 2024
console.log(plainDate.month); // Výstup: 10
console.log(plainDate.day); // Výstup: 27
Aritmetika s daty
Pro přičítání nebo odčítání dnů, týdnů, měsíců nebo roků použijte metody `plus` a `minus`. Tyto metody vracejí nový objekt `Temporal.PlainDate`:
const nextWeek = plainDate.plus({ days: 7 });
console.log(nextWeek.toString()); // Výstup: 2024-11-03
const lastMonth = plainDate.minus({ months: 1 });
console.log(lastMonth.toString()); // Výstup: 2024-09-27
Porovnávání dat
Data můžete porovnávat pomocí metody `compare`:
const date1 = new Temporal.PlainDate(2024, 10, 27);
const date2 = new Temporal.PlainDate(2024, 11, 15);
console.log(Temporal.PlainDate.compare(date1, date2)); // Výstup: -1 (date1 je dříve než date2)
Práce s časy
Vytvoření `Temporal.PlainTime`
Pro vytvoření `Temporal.PlainTime` použijte konstruktor:
const plainTime = new Temporal.PlainTime(10, 30, 0); // Hodina, Minuta, Sekunda
console.log(plainTime.toString()); // Výstup: 10:30:00
Nebo použijte metodu `from` s časovým řetězcem ve formátu ISO 8601:
const plainTimeFromString = Temporal.PlainTime.from('10:30:00');
console.log(plainTimeFromString.toString()); // Výstup: 10:30:00
Získání složek času
console.log(plainTime.hour); // Výstup: 10
console.log(plainTime.minute); // Výstup: 30
console.log(plainTime.second); // Výstup: 0
Aritmetika s časy
const later = plainTime.plus({ minutes: 15 });
console.log(later.toString()); // Výstup: 10:45:00
Společná práce s datem a časem
Vytvoření `Temporal.PlainDateTime`
Objekt `Temporal.PlainDateTime` můžete vytvořit přímo nebo spojením `Temporal.PlainDate` a `Temporal.PlainTime`:
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
console.log(plainDateTime.toString()); // Výstup: 2024-10-27T10:30:00
const date = new Temporal.PlainDate(2024, 10, 27);
const time = new Temporal.PlainTime(10, 30, 0);
const combinedDateTime = date.toPlainDateTime(time);
console.log(combinedDateTime.toString()); // Výstup: 2024-10-27T10:30:00
Časová pásma
Správné zpracování časových pásem je klíčové pro aplikace, které pracují s uživateli v různých lokalitách. Temporal API poskytuje robustní podporu časových pásem prostřednictvím objektů `Temporal.ZonedDateTime` a `Temporal.TimeZone`.
Vytvoření `Temporal.ZonedDateTime`
Pro vytvoření `Temporal.ZonedDateTime` potřebujete `Temporal.PlainDateTime` a identifikátor časového pásma. Identifikátory časových pásem jsou založeny na databázi časových pásem IANA (např. `America/Los_Angeles`, `Europe/London`, `Asia/Tokyo`).
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
console.log(zonedDateTime.toString()); // Výstup: 2024-10-27T10:30:00-07:00[America/Los_Angeles] (Offset se bude lišit v závislosti na pravidlech letního času)
Alternativně můžete vytvořit `Temporal.ZonedDateTime` z `Instant`.
const instant = Temporal.Instant.fromEpochSeconds(1666866600); // Příklad časového razítka
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO(timeZone); // Časové pásmo jako 'America/Los_Angeles'
console.log(zonedDateTimeFromInstant.toString());
Převod mezi časovými pásmy
Objekt `Temporal.ZonedDateTime` můžete převést do jiného časového pásma pomocí metody `withTimeZone`:
const newTimeZone = 'Europe/London';
const zonedDateTimeInLondon = zonedDateTime.withTimeZone(newTimeZone);
console.log(zonedDateTimeInLondon.toString()); // Výstup: 2024-10-27T18:30:00+01:00[Europe/London]
Práce s offsety časových pásem
Metoda `getOffsetStringFor` objektu `Temporal.TimeZone` poskytuje řetězec s offsetem pro daný `Temporal.Instant`:
const timeZoneObject = new Temporal.TimeZone(timeZone);
const offsetString = timeZoneObject.getOffsetStringFor(zonedDateTime.toInstant());
console.log(offsetString); // Výstup: -07:00 (V závislosti na pravidlech letního času)
Pro přesné výpočty je nezbytné používat správné identifikátory časových pásem IANA. Tyto identifikátory jsou pravidelně udržovány a aktualizovány, aby odrážely změny v letním čase a hranicích časových pásem.
Doby trvání (Durations)
Objekt `Temporal.Duration` reprezentuje časový úsek. Lze jej použít k přičítání nebo odčítání od dat a časů.
Vytvoření `Temporal.Duration`
Objekt `Temporal.Duration` můžete vytvořit pomocí konstruktoru, kde specifikujete roky, měsíce, dny, hodiny, minuty, sekundy, milisekundy, mikrosekundy a nanosekundy:
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9); // Roky, Měsíce, Dny, Hodiny, Minuty, Sekundy, Milisekundy, Mikrosekundy, Nanosekundy
console.log(duration.toString()); // Výstup: P1Y2M3DT4H5M6.007008009S
Nebo pomocí řetězce doby trvání ve formátu ISO 8601:
const durationFromString = Temporal.Duration.from('P1Y2M3DT4H5M6S');
console.log(durationFromString.toString()); // Výstup: P1Y2M3DT4H5M6S
Přičítání dob trvání k datům a časům
const plainDate = new Temporal.PlainDate(2024, 10, 27);
const duration = new Temporal.Duration(0, 0, 7); // 7 dní
const newDate = plainDate.plus(duration);
console.log(newDate.toString()); // Výstup: 2024-11-03
Upozorňujeme, že přičítání dob trvání, které zahrnují měsíce nebo roky, k datům vyžaduje pečlivé zvážení, protože počet dní v měsíci nebo roce se může lišit.
Kalendářní systémy
Temporal API podporuje různé kalendářní systémy kromě gregoriánského kalendáře. To je klíčové pro aplikace, které potřebují zpracovávat data v různých kulturních kontextech. Ačkoliv je podpora stále ve vývoji, poskytuje základ pro budoucí rozšíření.
Použití alternativních kalendářů
Chcete-li použít konkrétní kalendář, můžete jej specifikovat při vytváření objektů Temporal:
const hebrewDate = new Temporal.PlainDate(5785, 1, 1, { calendar: 'hebrew' });
console.log(hebrewDate.toString()); // Konkrétní výstup se může lišit v závislosti na implementaci a formátování. V době psaní tohoto článku vyžaduje v mnoha prostředích polyfill.
Důležité: Podpora pro negregoriánské kalendáře může vyžadovat polyfilly nebo specifickou podporu prohlížeče/prostředí. Zkontrolujte dokumentaci Temporal API a tabulky kompatibility prohlížečů pro nejnovější informace.
Formátování dat a časů
Zatímco Temporal API se zaměřuje na manipulaci s datem a časem, formátování je obvykle řešeno pomocí objektu `Intl.DateTimeFormat`, který je součástí Internationalization API. Objekty Temporal bezproblémově spolupracují s `Intl.DateTimeFormat`.
Použití `Intl.DateTimeFormat`
Zde je ukázka, jak formátovat `Temporal.PlainDate` pomocí `Intl.DateTimeFormat`:
const plainDate = new Temporal.PlainDate(2024, 10, 27);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatter.format(plainDate)); // Výstup: October 27, 2024
const formatterGerman = new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatterGerman.format(plainDate)); // Výstup: 27. Oktober 2024
Možnosti formátu si můžete přizpůsobit podle svých potřeb. Prvním argumentem `Intl.DateTimeFormat` je lokalita (locale), která určuje jazyk a regionální konvence použité pro formátování. Použití různých lokalit (např. 'en-US', 'de-DE', 'fr-FR', 'ja-JP') vytváří různé výstupní formáty.
Formátování `Temporal.ZonedDateTime`
Formátování `Temporal.ZonedDateTime` je podobné, ale do výstupu můžete zahrnout i informace o časovém pásmu:
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'short' });
console.log(formatter.format(zonedDateTime)); // Výstup: October 27, 2024, 10:30 AM PDT (Zkratka časového pásma závisí na pravidlech letního času)
Osvědčené postupy pro internacionalizaci
Při práci s daty a časy v globálním kontextu mějte na paměti následující osvědčené postupy:
- Používejte identifikátory časových pásem IANA: Pro přesné zpracování časových pásem vždy používejte identifikátory časových pásem IANA (např. `America/Los_Angeles`, `Europe/London`).
- Mějte na paměti letní čas: Letní čas (DST) může ovlivnit offsety časových pásem. Temporal API automaticky zpracovává přechody na letní čas.
- Používejte `Intl.DateTimeFormat` pro formátování: Pro formátování dat a časů podle lokality uživatele používejte objekt `Intl.DateTimeFormat`.
- Zvažte kalendářní systémy: Pokud vaše aplikace potřebuje podporovat uživatele v různých kulturních kontextech, zvažte použití alternativních kalendářních systémů.
- Ukládejte data a časy v UTC: Při ukládání dat a časů do databáze je osvědčeným postupem ukládat je v UTC (Koordinovaný světový čas), abyste se vyhnuli problémům s časovými pásmy. Poté je pro účely zobrazení převeďte na místní čas. Temporal poskytuje metody pro převod do a z UTC.
- Důkladně testujte: Testujte svou aplikaci s různými časovými pásmy, lokalitami a kalendářními systémy, abyste zajistili, že funguje správně pro všechny uživatele.
Porovnání Temporal API se starším objektem Date
Zde je tabulka zdůrazňující klíčové rozdíly a výhody Temporal API v porovnání se starším objektem `Date`:
Vlastnost | Starší objekt `Date` | Temporal API |
---|---|---|
Měnitelnost | Měnitelný (upravuje původní objekt) | Neměnný (vrací nové objekty) |
Podpora časových pásem | Omezená a často problematická | Robustní a přesná, založená na databázi časových pásem IANA |
API | Nekonzistentní a obtížně použitelné | Přehledné, konzistentní a intuitivní |
Přesnost | Milisekunda | Nanosekunda |
Kalendářní systémy | Omezeno na gregoriánský | Podporuje alternativní kalendářní systémy (s vyvíjející se podporou) |
Internacionalizace | Vyžaduje externí knihovny pro robustní internacionalizaci | Vestavěná podpora a bezproblémová integrace s `Intl.DateTimeFormat` |
Podpora v prohlížečích a polyfilly
Jelikož se jedná o relativně nové API, podpora Temporal API v prohlížečích se stále vyvíjí. Zkontrolujte nejnovější tabulky kompatibility prohlížečů (např. na MDN Web Docs), abyste zjistili, které prohlížeče a prostředí jej nativně podporují. Pro starší prohlížeče nebo prostředí bez nativní podpory můžete použít polyfilly, které poskytnou funkcionalitu Temporal API. Vyhledejte na webu „Temporal API polyfill“ a najděte vhodné možnosti.
Závěr
JavaScript Temporal API představuje významný krok vpřed ve zpracování dat a časů v JavaScriptu. Jeho neměnnost, přehledné API, robustní podpora časových pásem a schopnosti kalendářních systémů z něj činí mocný nástroj pro vývojáře, kteří vytvářejí aplikace, jež potřebují pracovat s daty a časy přesně a spolehlivě v různých mezinárodních kontextech. Ačkoli se podpora v prohlížečích stále vyvíjí, výhody Temporal API stojí za to se je naučit a přijmout pro nové projekty. Přijetím Temporal API a dodržováním osvědčených postupů pro internacionalizaci můžete vytvářet aplikace, které poskytují bezproblémový a přesný zážitek s datem a časem pro uživatele po celém světě.